package cn.tpshion.config.websocket;

import cn.tpshion.config.common.JsonUtil;
import cn.tpshion.config.domain.dto.MessageDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint(value = "/ws/{id}")
@Component
@Slf4j
public class WebSocketServer {

    private static final AtomicInteger OnlineCount = new AtomicInteger(0);

    private static Map<Session, String> sessionMap = new ConcurrentHashMap<>(50);

    @PostConstruct
    public void init() {
        log.info("WebSocketServer init...");
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("id") String id) {
        sessionMap.put(session, id);
        int cnt = OnlineCount.incrementAndGet(); // 在线数加1
        log.info("有连接加入，id:{} 当前连接数为：{}", id, cnt);
        MessageDTO messageDTO = new MessageDTO();
        messageDTO.setId(id);
        messageDTO.setData("连接成功");
        try {
            sendMessage(id, JsonUtil.obj2String(messageDTO));
        } catch (Exception e) {
            log.error("连接成功，id:{} 发送成功消息失败：{}", id,e.getMessage(), e);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        sessionMap.remove(session);
        int cnt = OnlineCount.decrementAndGet();
        log.info("有连接关闭，当前连接数为：{}", cnt);
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        String id = sessionMap.get(session);
        log.info("来自id:{}的消息：{}",id ,message);
    }

    /**
     * 出现错误
     * @param session
     * @param e
     */
    @OnError
    public void onError(Session session, Throwable e) {
        log.error("id:{}, 发生错误:{}",sessionMap.get(session), e.getMessage(),e);
    }

    /**
     * 发送消息，实践表明，每次浏览器刷新，session会发生变化。
     * @param id
     * @param message
     */
    public void sendMessage(String id, String message) throws IOException {
        for (Map.Entry<Session, String> entry : sessionMap.entrySet()) {
            if(entry.getValue().equals(id)){
                Session session = entry.getKey();
                if(session != null){
                    synchronized(session){
                        session.getBasicRemote().sendText(message);
                    }
                }
            }
        }
    }
}
